/******************************************************************************
**
** File name: 	uhwinit.c
**
** Description:	Basic hardware initialization required for RTOS Unit
**				Tests execution. Targets supported:
**				- ATXmega32D4 (AVRSIM)
**				- ATXmega_TBD (HW)
**				32D4 is the smallest (from resource perspectives) chip from 
**				Xmega family. 
**
** Change history:
**	
** 07/10/2011 - AK - File created. 
** 10/10/2011 - AK - Timer control services are separated from initialization
** 11/20/2011 - AK - Two timers support, removed support for AVRSIM
** 03/20/2011 - AK - Changing back to the simulator version
** 
******************************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include "uhwinit.h"


/* Forward function declarations */
void CCPWrite( volatile uint8_t * address, uint8_t value );

#if !defined( __AVR_ATxmega32D4__ )
#warning "No other target is yet tested except ATxmega32D4!!!"
#endif	/* __AVR_ATxmega32D4__ */

/******************************************************************************
**
** FUNCTION:	utst_init_gpio( void )
**
** DESCRIPTION:	No port initialization is required now.	All GPIO pins are 
**				in its default (after reset) state.
**
** PASSED:      void
** RETURNS:		void
** USES:		-
** STACK:		-
** CALLS:		-
** ASSUMES:		-
** NOTES:		Will get back to this service if external crystal is used.
**				Probably will use some GPIO as debug pin out.
**
******************************************************************************/
void utst_init_gpio( void )
{
	return;
}

/******************************************************************************
**
** FUNCTION:	void utst_init_clksys( void )
**
** DESCRIPTION:	Configure the system clock to use internal 2MHz oscillator.
**				Internal 32KHz oscillator is used for calibration. This 
**				function is required only in case of real hardware is used.
**
** PASSED:      void
** RETURNS:		void
** USES:		-
** STACK:		-
** CALLS:		-
** ASSUMES:		-
** NOTES:		Don't use with AVRSIM
**
******************************************************************************/
void utst_init_clksys( void )
{
	// TBD
	// Need to develop the version that works under AVRSIM

	return;
}


/******************************************************************************
**
** FUNCTION:	void utst_init_pmic( void )
**
** DESCRIPTION:	Configures Xmega interrupt controller.
**				
**
** PASSED:      void
** RETURNS:		void
** USES:		-
** STACK:		-
** CALLS:		-
** ASSUMES:		-
** NOTES:		This function is a must for both AVRSIM and HW
**
******************************************************************************/
void utst_init_pmic( void )
{
	// Set vector location to application
	uint8_t temp = PMIC.CTRL & ~PMIC_IVSEL_bm;
	CCP = CCP_IOREG_gc;
	PMIC.CTRL = temp;
	
	//PMIC.CTRL &= ~PMIC_RREN_bm;	// Disable round-robin
	PMIC_CTRL |= PMIC_RREN_bm;		// Enable round-robin for LOW level interrupts
	
	// Enable all low/medium/high levels interrupts
	PMIC.CTRL |= (PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm);
}

/******************************************************************************
**
** FUNCTION:	void CCPWrite( volatile uint8_t * address, uint8_t value )
**
** DESCRIPTION: CCP write helper function written in assembly.		
**
** PASSED:      address - A pointer to the address to write to.
** 				value   - The value to put in to the register.
** RETURNS:		void
** USES:		-
** STACK:		-
** CALLS:		-
** ASSUMES:		-
** NOTES:		-
**
******************************************************************************/
void CCPWrite( volatile uint8_t * address, uint8_t value )
{
	volatile uint8_t * tmpAddr = address;
#ifdef RAMPZ
	RAMPZ = 0;
#endif
	asm volatile(
		"movw r30,  %0"	      "\n\t"
		"ldi  r16,  %2"	      "\n\t"
		"out   %3, r16"	      "\n\t"
		"st     Z,  %1"       "\n\t"
		:
		: "r" (tmpAddr), "r" (value), "M" (CCP_IOREG_gc), "i" (&CCP)
		: "r16", "r30", "r31"
		);
}